package pimmodel;

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 
 * Klasse KontaktList:<br>
 * Klasse fuer die Verwaltung einer Liste, <br>
 * die mit Elementen des Typs IKontakt gefuellt ist.
 * 
 * @authors (Torsten Mansfeld, Thomas Schoenfeld)
 * @version (20120908_01)
 * 
 */
public class KontaktList extends PimList implements IKontaktList {
	
	// Meldungskonstanten
	private	static	final	String			IKONTAKT		= "Das uebergebene Objekt ist nicht vom Typ IKontakt.";
	private	static	final	String			KONTAKTNAME		= "Der uebergebene Kontaktname ist kein gueltiger String.";
	private	static	final	String			KONTAKTLISTE	= "Das uebergebene Objekt ist null.";
	
	
	
	// Konstanten
	private static	final	String			DATEINAME		= "kontaktliste.dat";
	
	
	
	// Instanzvariablen
	private					List<IKontakt>	kontaktliste;
	
	
	
	/**
	 * Standard-Konstruktor der Klasse KontaktList
	 */
	public KontaktList() {
		
		kontaktliste = new ArrayList<IKontakt>();
		
	}
	
	/**
	 * Kopierkonstruktor der Klasse KontaktList, erstellt tiefe Kopie
	 * 
	 * @param	IKontaktList	die zu kopierende Kontaktliste	
	 * 
	 * @throws					NullPointerException falls das uebergebene Objekt null ist.
	 * @throws					IllegalArgumentException falls ein Listenelement nicht vom Typ IKontakt ist. 
	 */
	public KontaktList( IKontaktList kontaktlisteNeu ) {
		
		this();
		
		if ( kontaktlisteNeu == null )
			throw new NullPointerException( IKONTAKT );
		
		for ( IKontakt kontakt : kontaktlisteNeu.getKontaktliste() ) {			
			
			kontaktHinzufuegen( new Kontakt ( kontakt ) );
			
		}
		
		this.setChanged();
		this.notifyObservers( kontaktlisteNeu );
		
	}
	
	
		
	// Getter und Setter Methoden
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#getKontaktliste()
	 */
	@Override
	public List<IKontakt> getKontaktliste() {
		
		sortieren();
		
		return this.kontaktliste;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#setKontaktliste(java.util.List)
	 */
	@Override
	public void setKontaktliste( final List<IKontakt> kontaktliste ) {
		
		if ( kontaktliste == null )
			throw new NullPointerException( KONTAKTLISTE );
		
		this.kontaktliste = new ArrayList<IKontakt>();
		
		for ( IKontakt kontakt : kontaktliste ) {
			
			if ( !( kontakt instanceof IKontakt ) )
				throw new IllegalArgumentException( IKONTAKT );
		
			kontaktHinzufuegen( new Kontakt( kontakt ) );
			
		}
		
		sortieren();
		
		this.setChanged();
		this.notifyObservers( kontaktliste );
		
	}
	
	
	
	// sonstige Methoden

	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#kontaktErsetzen(pimmodel.IKontakt, pimmodel.IKontakt)
	 */	
	@Override
	public boolean kontaktErsetzen( final IKontakt bearKont, final IKontakt orgKont ) {
		
		if ( !( bearKont instanceof IKontakt ) || !( orgKont instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );
		
		boolean ret = kontaktLoeschen( orgKont );
		
		if ( ret )
			ret = kontaktHinzufuegen( bearKont );
		
		return ret;
		
	}
		
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#kontaktHinzufuegen(pimmodel.IKontakt)
	 */
	@Override
	public boolean kontaktHinzufuegen( final IKontakt neuKont ) {
		
		if ( !( neuKont instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );
		
		boolean ret = this.kontaktliste.add( neuKont );
		
		sortieren();
		
		this.setChanged();
		this.notifyObservers( neuKont );
		
		return ret; 
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#kontaktLoeschen(pimmodel.IKontakt)
	 */
	@Override
	public boolean kontaktLoeschen( final IKontakt loeschKont ) {
		
		if ( !( loeschKont instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );
		
		boolean ret = this.kontaktliste.remove( loeschKont );
		
		sortieren();
		
		this.setChanged();
		this.notifyObservers( loeschKont );
		
		return ret;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#kontaktLiefern(int)
	 */
	@Override
	public IKontakt kontaktLiefern( final int index ) {
		
		return this.kontaktliste.get( index );
		
	}
		
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#kontaktNameSuchen(java.lang.String)
	 */
	@Override
	public int kontaktNameSuchen( final String kontaktName ) {
		
		if ( !( kontaktName instanceof String ) || kontaktName.trim().isEmpty() )
			throw new IllegalArgumentException( KONTAKTNAME );	
		
		int index = -1; // 0 ist das erste Element!
		
		for( int i = 0; i < size(); i++ ){

			if ( kontaktName.trim().equals( kontaktLiefern( i ).getName() ) ) {
				
				index = i;
				
			}
			
		}
		
		return ( index );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#kontaktSuchen(pimmodel.IKontakt)
	 */
	@Override
	public int kontaktSuchen( final IKontakt suchKontakt ) {
		
		if ( !( suchKontakt instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );	
				
		return this.kontaktliste.indexOf( suchKontakt );
		
	}
	
	public List<IKontakt> kontaktsuchenNamen(String name){
		List<IKontakt>	ergebnis=new ArrayList<IKontakt>();
		for (int i=0;i<this.kontaktliste.size();i++){
			if (this.kontaktliste.get(i).getName().equals(name)){
				ergebnis.add(this.kontaktliste.get(i));
			}
		}
		return ergebnis;
	}
	
	public List<IKontakt> kontaktsuchenVornamen(String vorname){
		List<IKontakt>	ergebnis=new ArrayList<IKontakt>();
		for (int i=0;i<this.kontaktliste.size();i++){
			if (this.kontaktliste.get(i).getVorname().equals(vorname)){
				ergebnis.add(this.kontaktliste.get(i));
			}
		}
		return ergebnis;
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#toArray()
	 */
	@Override
	public Object[] toArray() {
		
		return this.kontaktliste.toArray();
		
	}
		
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#clear()
	 */
	@Override
	public void clear() {
		
		this.kontaktliste = new ArrayList<IKontakt>();
		
		this.setChanged();
		this.notifyObservers( this.kontaktliste );
		
	}
	
	/**
	 * clone					liefert flache Kopie der Kontaktliste
	 * 
	 * @return					flache Kopie der Kontaktliste
	 */
	@Override
	public IKontaktList clone() {
		
		return this;
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#isEmpty()
	 */
	@Override
	public boolean isEmpty() {
		
		return this.kontaktliste.isEmpty();
		
	}	
		
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#size()
	 */
	@Override
	public int size() {
		
		return this.kontaktliste.size();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#toString()
	 */
	@Override
	public String toString() {
		
		String ausgabe = "";
		
		sortieren();
		
		for ( IKontakt kontakt : this.kontaktliste ) {
			
			ausgabe += kontakt + "\n";
			
		}
		
		return ausgabe;
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#hashCode()
	 */
	@Override
	public int hashCode() {
		
		final int prime = 31;
		
		int result = 1;
		
		result = prime * result	+ ( ( this.kontaktliste == null ) ? 0 : this.kontaktliste.hashCode() );
		
		return result;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#equals(java.lang.Object)
	 */
	@Override
	public boolean equals( final Object obj ) {
		
		if ( this == obj )
			return true;
		
		if ( obj == null )
			return false;
		
		if ( getClass() != obj.getClass() )
			return false;
		
		IKontaktList other = ( IKontaktList ) obj;
		
		if ( this.kontaktliste == null ) {
			
			if (other.getKontaktliste() != null)
				return false;
			
		}
		else if ( !this.kontaktliste.equals( other.getKontaktliste() ) )
			return false;
		
		return true;
		
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pimmodel.IKontaktList#speichern()
	 */
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#speichern()
	 */
	@Override
	public void speichern() throws FileNotFoundException, IOException {
		
		ObjectOutputStream outputStream = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( DATEINAME ) ) );
		
		outputStream.writeObject( this.kontaktliste );
		
		outputStream.close();
		
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pimmodel.IKontaktList#laden()
	 */
	/* (non-Javadoc)
	 * @see pimmodel.IKontaktList#laden()
	 */
	@Override
	@SuppressWarnings("unchecked")
	public void laden() throws IOException, ClassNotFoundException {
		
		ObjectInputStream inputStream = new ObjectInputStream( new BufferedInputStream( new FileInputStream( DATEINAME ) ) );
		
		this.kontaktliste = ( List<IKontakt> ) inputStream.readObject();
		
		inputStream.close();
		
	}	
	
	// interne Sortier-Methode
	private void sortieren() {
		
		Collections.sort( this.kontaktliste );

	}
	
}
